package cn.marknum.gateway.filter;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author zhangzhao    2022-08-05 18:36
 */
@Component
public class AuthUtil {

    private final Logger logger = LoggerFactory.getLogger(AuthUtil.class);

    private final Set<String> authPath = new HashSet<>();
    private long updateTime;
    private Integer outTime = 5 * 60 * 1000;
    @Value("${auth.excludes:#{null}}")
    private String excludes;
    private List<String> excludeList;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @PostConstruct
    public void init() {
        if (StrUtil.isNotBlank(excludes)) {
            excludeList = Arrays.asList(excludes.split(","));
        }
    }

    public boolean filtration(String uri) {
        if (System.currentTimeMillis() - updateTime > outTime) {
            authPath.clear();
            Set<String> authPathKeys = stringRedisTemplate.keys("AUTH_PATH:*");
            authPathKeys.forEach(key -> {
                Set<String> paths = stringRedisTemplate.<String, String>boundHashOps(key).keys();
                if (!paths.isEmpty()) {
                    authPath.addAll(paths);
                }
            });
            updateTime = System.currentTimeMillis();
            logger.info("当前[时间:{}]加载的鉴权服务key有：{}", updateTime, JSON.toJSONString(authPathKeys));
        }
        int index = uri.indexOf("?");
        if (index > 0) {
            uri = uri.substring(0, index);
        }
        if (CollUtil.isNotEmpty(excludeList))
            for (String exclude : excludeList) {
                if (uri.matches(exclude)) {
                    return true;
                }
            }
        for (String path : authPath) {
            if (uri.matches(path)) {
                return false;
            }
        }
        return true;
    }
}
